﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net;
using System.Net.Sockets;
using System.Threading;


namespace LinnCorLib.Net
{
    public class ChatServer
    {
        private Socket server = null;       
        private int port = 7777;
        private Dictionary<string, Client> clientList = new Dictionary<string, Client>();
        private Thread serverThread = null;
        private object thisLock = new object();

        public bool stopped { get; private set; }


        private ChatServer() { }

        public ChatServer(int port)
        {
            this.port = port;
            stopped = true;
        }


        public void Start(int backlog)
        {
            stopped = false;

            serverThread = new Thread(new ThreadStart(Run));
            serverThread.IsBackground = true;
            serverThread.Start();
        }

        public void Run()
        {
            server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
            server.Bind(new IPEndPoint(IPAddress.Any, port));

            IPHostEntry host = Dns.GetHostEntry("localhost");
            IPAddress ipAddr = Dns.GetHostEntry("localhost").AddressList[0];

            Console.WriteLine("[Monster Server Ver0.01] : Computer Name :  {0} {1}", host.HostName, ipAddr);
            Console.WriteLine("[Monster Server Ver0.01] : 서버가 시작되었습니다. ( Port Number : {0} )", port);

            server.Listen(10);
            Console.WriteLine("[Monster Server Ver0.01] : Client Lisening...");

            try
            {
                while (stopped == false)
                {
                    Socket client = server.Accept();

                    RegistClient(client);

                    Console.WriteLine("[Monster Server Ver0.01] : Client 접속 IP Addr : {0} ", client.RemoteEndPoint);
                    //client.BeginReceive(byteReceiveMessage, 0, 1024, SocketFlags.None, new AsyncCallback(CallBack_RecieveMessage), client);
                }
            }
            catch (ThreadAbortException ex)
            {
                Console.WriteLine("[Monster Server Ver0.01] : Error : {0} ", ex.Message);
            }
        }

        private void RegistClient(Socket client)
        {
            string id = clientList.Count.ToString();

            RemoveClient(id);
            clientList.Add(id, new Client(id, client, this));
        }

        public void RemoveClient(string id)
        {
            if (clientList.ContainsKey(id) == true)
                clientList.Remove(id);
        }

        public void ReceiveMessage(string message)
        {
            SendMessageAll(message);
        }

        public void SendMessage(string id, string msg) //메시지를 보낸다.
        {
            if (clientList.ContainsKey(id) == true)
            {
                clientList[id].ClientSend(msg);
                Console.WriteLine("[Monster Server Ver0.01] : {0}{1} ", id, "에게 전송완료");
            }
        }

        public void SendMessageAll(string msg) //메시지를 보낸다.
        {
            if (clientList.Count == 0)
            {
                Console.WriteLine("[Monster Server Ver0.01] : {0} ", "접속된 클라이언트가 없음.");
                return;
            }

            foreach (var id in clientList.Keys)
                SendMessage(id, msg);
        }

        public void Stop()
        {
            lock (thisLock)
            {
                stopped = true;
            }

            if (server != null)
            {
                server.Close();
                server = null;
            }

            if (serverThread != null)
            {
                serverThread.Abort();
                serverThread = null;
            }

            Console.WriteLine("[Monster Server Ver0.01] : 서버가 중지되었습니다.");
        }
    }
}
